package miage.m1.poo.arborescence;
import java.lang.*;
import java.io.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.HeadlessException;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Iterator;

public class JTreeFolder extends JFrame {

	MyRenderer myRenderer = new MyRenderer();
  protected DefaultMutableTreeNode racine;
  protected JTree tree;
  protected JScrollPane scrollpane;
  final static int MAX_LEVEL = 2; // niveau max de descente "direct" dans l'arborescence
  
  public JTreeFolder() throws HeadlessException {
    File[] drive;
    tree = new JTree();
    tree.setCellRenderer(myRenderer);

    // creation du noeud superieur
    racine = new FSNode("Poste de travail");

    // creation d'un noeud pour chaque lecteur
    drive = File.listRoots();
    for (int i = 0 ; i < drive.length ; i++) {
      FSNode node = new FSNode(drive[i]/* ,drive[i]*/);
      addFolder(drive[i], node); // on descend dans l'arborescence du lecteur jusqu'a MAX_LEVEL
      racine.add(node);
    }

    // Gestion d'evenement sur JTree (on ecoute les evenements TreeExpansion)
    tree.addTreeExpansionListener(new TreeExpansionListener() {
      public void treeExpanded(TreeExpansionEvent e) {
        // lorsqu'un noeud est ouvert
        // on descend dans l'arborescence du noeud jusqu'a MAX_LEVEL
        TreePath path = e.getPath();
        FSNode node = (FSNode)path.getLastPathComponent();
        addFolder(node);
        ((DefaultTreeModel)tree.getModel()).reload(node); // on recharche uniquement le noeud
      }
      public void treeCollapsed(TreeExpansionEvent e) {
        // lorsqu'un noeud est referme
        //RIEN
      }
    });

    tree.addMouseListener(new MouseListener (){
      /**
       * mouseClicked
       *
       * @param e MouseEvent
       */
      public void mouseClicked(MouseEvent e) {
    	  
      }

      /**
       * mouseEntered
       *
       * @param e MouseEvent
       */
      public void mouseEntered(MouseEvent e) {
      }

      /**
       * mouseExited
       *
       * @param e MouseEvent
       */
      public void mouseExited(MouseEvent e) {
      }

      /**
       * mousePressed
       *
       * @param e MouseEvent
       */
      public void mousePressed(MouseEvent e) {
      }

      /**
       * mouseReleased
       *
       * @param e MouseEvent
       */
      public void mouseReleased(MouseEvent e) {
        TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
        if (selPath != null) {
          System.out.println(selPath);
        }
      }
    });


    tree.addKeyListener(new KeyListener() {
      /**
       * keyPressed
       *
       * @param e KeyEvent
       */
      public void keyPressed(KeyEvent e) {
      }

      /**
       * keyReleased
       *
       * @param e KeyEvent
       */
      public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == e.VK_ENTER ) {
          TreePath selPath = tree.getSelectionPath();
          System.out.println(selPath);
        }
      }

      /**
       * keyTyped
       *
       * @param e KeyEvent
       */
      public void keyTyped(KeyEvent e) {
      }
    });

    // alimentation du JTree
    DefaultTreeModel model = new DefaultTreeModel(racine);
    tree.setModel(model);


    // ajout du JTree au formulaire
    JPanel jp = new JPanel();
    scrollpane = new JScrollPane();
    jp.add(scrollpane);
    scrollpane.getViewport().add(tree, null);
    JPanel jp2 = new JPanel(new GridLayout(3,3));
    
    
    
    
    
    getContentPane().add(jp, BorderLayout.WEST);
    getContentPane().add(jp2, BorderLayout.EAST);

    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  /**
   * MAIN
   * @param arg
   */
  
  /**
   * Recuperation des sous-elements d'un repertoire
   * @param driveOrDir
   * @param node
   */
  public void addFolder(File driveOrDir, DefaultMutableTreeNode node) {
    setCursor(new Cursor(3)); // WAIT_CURSOR est DEPRECATED
    addFolder(driveOrDir, node, 0);
    setCursor(new Cursor(0)); // DEFAULT_CURSOR est DEPRECATED
  }

  /**
   * Recuperation des sous-elements d'un repertoire
   * (avec niveau pour recursivite et arret sur MAX_LEVEL)
   * @param driveOrDir File
   * @param node DefaultMutableTreeNode
   * @param level int
   */
  private void addFolder(File driveOrDir, DefaultMutableTreeNode node, int level) {
    File[] fileList;
    fileList = driveOrDir.listFiles();

    if (fileList != null) {
      sortFiles(fileList); // on tri les elements
    }

    // on ne cherche pas plus loin que le niveau maximal defini
    if (level > MAX_LEVEL - 1) {return;}

    // pour chaque element
    try {
      for (int i = 0; i < fileList.length; i++) {
        // en fonction du type d'element
        if (fileList[i].isDirectory()) {
          // si c'est un repertoire on cree un nouveau noeud
          FSNode dir = new FSNode(fileList[i].getName(), fileList[i]);
          node.add(dir);
          // on recherche les elements (recursivite)
          addFolder(fileList[i], dir, ++level);
        }
        /*
        if (fileList[i].isFile()) {
          // si c'est un fichier on ajoute l'element au noeud
          node.add(new FSNode(fileList[i].getName(), fileList[i]));
        }
        */
      }
    }
    catch (NullPointerException e) {
      // rien
    }
  }

  /**
   * Recuperation des sous-elements d'un noeud
   * @param node
   */
  public void addFolder(FSNode node) {
    setCursor(new Cursor(3)); // WAIT_CURSOR est DEPRECATED
    for (int i = 0 ; i < node.getChildCount() ; i++) {
      addFolder(((FSNode)node.getChildAt(i)).getFile(), (FSNode)node.getChildAt(i));
    }
    setCursor(new Cursor(0)); // DEFAULT_CURSOR est DEPRECATED
  }

  /**
   * Tri une liste de fichier
   * @param listFile
   */
  public void sortFiles(File[] listFile) {
    triRapide(listFile, 0, listFile.length - 1);
  }

  /**
   * QuickSort : Partition
   * @param listFile
   * @param deb
   * @param fin
   * @return
   */
  private int partition(File[] listFile, int deb, int fin) {
    int compt = deb;
    File pivot = listFile[deb];
    int i = deb - 1;
    int j = fin + 1;

    while (true) {
      do {
        j--;
      } while (listFile[j].getName().compareToIgnoreCase(pivot.getName()) > 0);
      do {
        i++;
      } while (listFile[i].getName().compareToIgnoreCase(pivot.getName()) < 0);
      if (i < j) {
        echanger(listFile, i, j);
      } else {
        return j;
      }
    }
  }

  /**
   * Tri rapide : quick sort
   * @param listFile
   * @param deb
   * @param fin
   */
  private void triRapide(File[] listFile, int deb, int fin) {
      if (deb < fin) {
        int positionPivot = partition(listFile, deb, fin);
        triRapide(listFile, deb, positionPivot);
        triRapide(listFile, positionPivot + 1, fin);
      }
  }

  /**
   * QuickSort : echanger
   * @param listFile
   * @param posa
   * @param posb
   */
  private void echanger(File[] listFile, int posa, int posb) {
    File tmpFile = listFile[posa];
    listFile[posa] = listFile[posb];
    listFile[posb] = tmpFile;
  }
  
  public static void main(String[] arg)
  {
      JTreeFolder Arbre = new JTreeFolder();
      Arbre.setTitle("Arborescence");
      Arbre.setSize(800,400);
      Arbre.setVisible(true);
  }


}
